#include "ir_nec.h"
#include "main.h"
#include "stdio.h"  // 包含sprintf函数
#include "usart.h"  // 包含串口相关函数
#include "delay_us.h"  // 包含DWT定时器相关函数
#include "stm32f1xx_ll_exti.h"  // 包含外部中断相关函数
#include "stm32f1xx_ll_gpio.h"  // 包含GPIO相关函数
#include "stm32f1xx.h"  // 包含NVIC和其他STM32相关函数

// NEC协议时序参数（针对反相信号，单位：微秒）
#define IR_NEC_IDLE_TIMEOUT_US         500000   // 空闲超时时间（1秒）
#define IR_NEC_LEADER_LOW_US           9000      // 引导码低电平时间
#define IR_NEC_FRAME_HIGH_US           4500      // 完整帧高电平时间
#define IR_NEC_REPEAT_HIGH_US          2250      // 重复帧高电平时间
#define IR_NEC_BIT1_LOW_US             1690      // 逻辑1低电平时间
#define IR_NEC_BIT0_LOW_US             560       // 逻辑0低电平时间
#define IR_NEC_HIGH_US                 560       // 固定高电平时间

// 总时长判断范围（高电平时间 + 低电平时间 ± 容差）
#define IR_NEC_LEADER_TOTAL_MIN        (IR_NEC_LEADER_LOW_US + IR_NEC_HIGH_US - 1000)
#define IR_NEC_LEADER_TOTAL_MAX        (IR_NEC_LEADER_LOW_US + IR_NEC_HIGH_US + 1000)
#define IR_NEC_FRAME_TOTAL_MIN         (IR_NEC_FRAME_HIGH_US + IR_NEC_HIGH_US - 500)
#define IR_NEC_FRAME_TOTAL_MAX         (IR_NEC_FRAME_HIGH_US + IR_NEC_HIGH_US + 500)
#define IR_NEC_REPEAT_TOTAL_MIN        (IR_NEC_REPEAT_HIGH_US + IR_NEC_HIGH_US - 500)
#define IR_NEC_REPEAT_TOTAL_MAX        (IR_NEC_REPEAT_HIGH_US + IR_NEC_HIGH_US + 500)
#define IR_NEC_BIT1_TOTAL_MIN          (IR_NEC_BIT1_LOW_US + IR_NEC_HIGH_US - 200)
#define IR_NEC_BIT1_TOTAL_MAX          (IR_NEC_BIT1_LOW_US + IR_NEC_HIGH_US + 200)
#define IR_NEC_BIT0_TOTAL_MIN          (IR_NEC_BIT0_LOW_US + IR_NEC_HIGH_US - 200)
#define IR_NEC_BIT0_TOTAL_MAX          (IR_NEC_BIT0_LOW_US + IR_NEC_HIGH_US + 200)
//uint32_t time_diff = 0;
// 解码状态枚举
typedef enum {
    IR_NEC_STATE_IDLE,               // 空闲状态
    IR_NEC_STATE_LEADER_LOW,         // 引导码低电平检测
    IR_NEC_STATE_FRAME_REPEAT_HIGH,  // 完整帧/重复帧高电平检测
    IR_NEC_STATE_DATA_LOW,           // 数据位低电平检测
} IR_NEC_StateTypedef;

// 字节位反转函数（低位在前转换）
static uint8_t reverseByteBits(uint8_t byte) {
    byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xAA);
    byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xCC);
    byte = ((byte >> 4) & 0x0F) | ((byte << 4) & 0xF0);
    return byte;
}

// 静态全局变量
static IR_NEC_StateTypedef ir_nec_state = IR_NEC_STATE_IDLE;
static uint32_t ir_nec_last_time = 0;
static uint32_t ir_nec_data_buffer = 0;
static uint8_t ir_nec_bit_count = 0;
static IR_NEC_DataTypedef ir_nec_data = {0};
static uint8_t ir_nec_data_ready = 0;
// time_diff在函数内部声明，避免重复初始化

// 初始化红外解码模块
void IR_NEC_Init(void) {
    /* 配置PB3引脚为红外接收输入引脚 */
    // 1. 设置PB3引脚为输入模式（浮空输入）
    LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_3, LL_GPIO_MODE_FLOATING);
    
    // 2. 初始化状态变量
    ir_nec_state = IR_NEC_STATE_IDLE;
    ir_nec_last_time = DWT_GetTick();
    ir_nec_data_ready = 0;
}

// 处理红外下降沿中断
void IR_NEC_ProcessEdge(void) {
    uint32_t current_time = DWT_GetTick();
    uint32_t time_diff = DWT_GetDeltaUs(ir_nec_last_time, current_time);
    ir_nec_last_time = current_time;

    switch (ir_nec_state) {
        case IR_NEC_STATE_IDLE:
            // 检测到足够长的空闲时间，准备接收新帧
            if (time_diff > IR_NEC_IDLE_TIMEOUT_US) {
                ir_nec_state = IR_NEC_STATE_LEADER_LOW;
            }
            break;

        case IR_NEC_STATE_LEADER_LOW:
            // 判断引导码总时长（9ms低 + 0.56ms高）
            if (time_diff >= 12000 && time_diff <= 16000) {
                // 完整帧：准备接收32位数据
                ir_nec_state = IR_NEC_STATE_DATA_LOW;
                ir_nec_data_buffer = 0;
                ir_nec_bit_count = 0;
                ir_nec_data.repeat = 0;
            } else if (time_diff >= IR_NEC_REPEAT_TOTAL_MIN && time_diff <= IR_NEC_REPEAT_TOTAL_MAX) {
                // 重复帧：直接标记重复标志
                ir_nec_data.repeat = 1;
                ir_nec_data.valid = 1;
                ir_nec_data_ready = 1;
                ir_nec_state = IR_NEC_STATE_IDLE;
            } else {
                // 无效帧，回到空闲状态
                ir_nec_state = IR_NEC_STATE_IDLE;
            }
            break;

        case IR_NEC_STATE_DATA_LOW:
            // 解析数据位（通过总时长判断0/1）
            ir_nec_data_buffer <<= 1;
            
            // 逻辑1：总时长 = 1690us低 + 560us高 ≈ 2250us
            if (time_diff >= 1800 && time_diff <= 2500) {
                ir_nec_data_buffer |= 1;
            }
            // 逻辑0：总时长 = 560us低 + 560us高 ≈ 1120us
            else if (time_diff >= 900 && time_diff <= 1300) {
                // 逻辑0无需额外操作（左移后最低位为0）
            }
            else {
                // 数据位无效，放弃当前帧
                ir_nec_state = IR_NEC_STATE_IDLE;
                break;
            }

            ir_nec_bit_count++;
            
            // 32位数据接收完成
            if (ir_nec_bit_count >= 32) {
                // 解析地址码和命令码（地址码是前两个字节，没有反码）
                uint8_t addr_high = (ir_nec_data_buffer >> 24) & 0xFF;
                uint8_t addr_low = (ir_nec_data_buffer >> 16) & 0xFF;
                ir_nec_data.command = (ir_nec_data_buffer >> 8) & 0xFF;
                ir_nec_data.command_inverse = ir_nec_data_buffer & 0xFF;
                
                // 每字节进行低位在前的反转处理
                addr_high = reverseByteBits(addr_high);
                addr_low = reverseByteBits(addr_low);
                ir_nec_data.command = reverseByteBits(ir_nec_data.command);
                ir_nec_data.command_inverse = reverseByteBits(ir_nec_data.command_inverse);
                
                // 合并前两个字节为16位地址码
                ir_nec_data.address = (addr_high << 8) | addr_low;
                
                // 只校验命令码的反码
                if (ir_nec_data.command == (~ir_nec_data.command_inverse & 0xFF)) {
                    ir_nec_data.valid = 1;
                    ir_nec_data_ready = 1;
                } else {
                    ir_nec_data.valid = 0;
                }
                
                ir_nec_state = IR_NEC_STATE_IDLE;
            }
            break;

        default:
            ir_nec_state = IR_NEC_STATE_IDLE;
            break;
    }
}

// 获取解码结果
uint8_t IR_NEC_GetData(IR_NEC_DataTypedef *data) {
    if (ir_nec_data_ready && data != NULL) {
        *data = ir_nec_data;
        ir_nec_data_ready = 0;
        ir_nec_data.valid = 0;  // 清除有效标志
        return 1;
    }
    return 0;
}

/**
 * @brief 处理解码后的红外数据
 * @note 应在主循环或任务中定期调用
 * @param 无
 * @retval 无
 */
void IR_NEC_Handle(void)
{
    // 功能已移至StartLCD_Task中实现，此函数保留为空以保持兼容性
}